package org.zzk.handler;

import com.google.gson.JsonObject;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.TooLongFrameException;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zzk.dao.CommandType;

import java.io.IOException;

@ChannelHandler.Sharable
public class TailExceptionHandler extends ChannelDuplexHandler {
    public static final TailExceptionHandler INSTANCE = new TailExceptionHandler();
    private static final Logger logger = LoggerFactory.getLogger(TailExceptionHandler.class);

    @Getter
    public enum ExceptionType {
        TooLongFrameException((byte) 1001, "数据帧过长，请检查协议格式"),
        DecoderException((byte) 1002, "协议解码失败"),
        ForceCloseConnect((byte) 1003, "远程主机关闭了连接"),
        ServerInternalError((byte) 9999, "服务器内部错误");

        private final byte code;
        private final String description;

        ExceptionType(byte code, String description) {
            this.code = code;
            this.description = description;
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // 1. 日志记录异常详情
        logger.info("未处理的管道异常: {}", ctx.channel().id(), cause);

        // 2. 构建错误响应协议
        JsonObject errorResp = getErrorResp(ctx, cause);

        if (!ctx.channel().isOpen()) {
            return;
        }

        // 3. 发送错误响应并关闭连接
        ByteBuf response = ChessPacketCodecHandler.encode(
                CommandType.fromCode(CommandType.ERROR.getCode()),
                errorResp
        );

        ctx.writeAndFlush(response)
                .addListener(ChannelFutureListener.CLOSE)
                .addListener(f -> {
                    if (!f.isSuccess()) {
                        logger.warn("发送错误响应失败: {}", ctx.channel().id(), f.cause());
                    }
                });
    }

    private static JsonObject getErrorResp(ChannelHandlerContext ctx, Throwable cause) {
        JsonObject errorResp = new JsonObject();
        errorResp.addProperty("status", "error");

        if (cause instanceof TooLongFrameException) {
            errorResp.addProperty("code", ExceptionType.TooLongFrameException.getCode());
            errorResp.addProperty("message", ExceptionType.TooLongFrameException.getDescription());
        } else if (cause instanceof DecoderException) {
            errorResp.addProperty("code", ExceptionType.DecoderException.getCode());
            errorResp.addProperty("message", ExceptionType.DecoderException.getDescription());
        } else if (cause instanceof IOException) {
            // 记录客户端异常断开日志（带客户端IP）
            String clientIp = ctx.channel().remoteAddress().toString();
            logger.warn("客户端强制断开: {} - {}", clientIp, cause.getMessage());
            // 立即释放资源
            ctx.channel().close();
        } else {
            errorResp.addProperty("code", ExceptionType.ServerInternalError.getCode());
            errorResp.addProperty("message", ExceptionType.ServerInternalError.getDescription());
        }
        return errorResp;
    }
}
